Passed
Push — master ( 395edf...edf3b4 )
by EMP
01:17
created

main.js ➔ addressCreate   F

Complexity

Conditions 18

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 26
rs 1.2
c 0
b 0
f 0
cc 18

How to fix   Complexity   

Complexity

Complex classes like main.js ➔ addressCreate often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"use strict";
2
3
sodium.ready.then(function() {
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
4
5
const ae = new AllEars(function(ok) {
1 ignored issue
show
Bug introduced by
The variable AllEars seems to be never declared. If this is a global, consider adding a /** global: AllEars */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
6
	if (ok) {
7
		document.getElementById("txt_skey").style.background = "#466";
8
		document.getElementById("txt_skey").maxLength = "64";
9
	} else {
10
		console.log("Failed to load All-Ears");
11
	}
12
});
13
14
function TabState(cur, max, btnDele, btnUpdt) {
15
	this.cur = cur;
16
	this.max = max;
17
	this.btnDele = btnDele;
18
	this.btnUpdt = btnUpdt;
19
}
20
21
const tabs = [
22
	new TabState(0, 0, false, true), // Inbox
23
	new TabState(0, 0, false, true), // Outbx
24
	new TabState(0, 2, true, false), // Write
25
	new TabState(0, 2, false, false), // Notes
26
	new TabState(0, 3, false, true) // Admin
27
];
28
29
let tab = 0;
30
const TAB_INBOX = 0;
31
const TAB_OUTBX = 1;
0 ignored issues
show
Unused Code introduced by
The constant TAB_OUTBX seems to be never used. Consider removing it.
Loading history...
32
const TAB_WRITE = 2;
33
const TAB_NOTES = 3;
34
const TAB_ADMIN = 4;
35
36
// Helper functions
37
function getCountryName(countryCode) {
38
	const opts = document.getElementById("gatekeeper_country");
39
40
	for (let i = 0; i < opts.length; i++) {
41
		if (opts[i].value === countryCode) {
42
			return opts[i].textContent;
43
		}
44
	}
45
46
	return "Unknown countrycode: " + countryCode;
47
}
48
49
function getCountryFlag(countryCode) {
50
	return sodium.to_string(new Uint8Array([
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
51
		240, 159, 135, 166 + countryCode.codePointAt(0) - 65,
52
		240, 159, 135, 166 + countryCode.codePointAt(1) - 65
53
	]));
54
}
55
56
function getMsgId(num) {
57
	let i;
58
	if (ae.GetExtMsgHeaders(num).toLowerCase().slice(0, 11) === "message-id:") {
59
		i = 0;
60
	} else {
61
		i = ae.GetExtMsgHeaders(num).toLowerCase().indexOf("\nmessage-id:");
62
		if (i < 1) return "ERR";
63
		i++;
64
	}
65
66
	const x = ae.GetExtMsgHeaders(num).slice(i + 11).trim();
67
	if (x[0] !== "<") return "ERR2";
68
	return x.slice(1, x.indexOf(">"));
69
}
70
71
function displayMsg(isInt, num) {
72
	document.getElementById("midright").scroll(0, 0);
73
74
	const ts = isInt? ae.GetIntMsgTime(num) : ae.GetExtMsgTime(num);
75
76
	document.getElementById("btn_reply").disabled = false;
77
	document.getElementById("btn_reply").onclick = function() {
78
		document.getElementById("write_recv").value = isInt? ae.GetIntMsgFrom(num) : ae.GetExtMsgFrom(num);
79
		document.getElementById("write_subj").value = "Re: " + (isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num));
80
		document.getElementById("write_rply").textContent = (isInt? "" : getMsgId(num));
81
		document.getElementById("btn_write").click();
82
		document.getElementById("div_write_1").hidden = false;
83
		document.getElementById("div_write_2").hidden = true;
84
		document.getElementById("write_body").focus();
85
		for (const opt of document.getElementById("write_from").options) {
86
			if (opt.value === (isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num))) {
87
				opt.selected = true;
88
			}
89
		}
90
	};
91
92
	document.getElementById("btn_mdele").disabled = false;
93
	document.getElementById("btn_mdele").onclick = function() {
94
		this.blur();
95
96
		ae.Message_Delete(isInt? ae.GetIntMsgIdHex(num) : ae.GetExtMsgIdHex(num), function(success) {
97
			if (!success) console.log("Failed delete");
98
		});
99
	}
100
101
	document.getElementById("msg").hidden = false;
102
	document.getElementById("msg").getElementsByTagName("h1")[0].textContent = isInt ? ae.GetIntMsgTitle(num) : ae.GetExtMsgTitle(num);
103
	document.getElementById("msg").getElementsByTagName("pre")[0].textContent = isInt ? ae.GetIntMsgBody(num) : ae.GetExtMsgBody(num);
104
105
	document.getElementById("readmsg_to").textContent = isInt ? ae.GetIntMsgTo(num) : ae.GetExtMsgTo(num);
106
	document.getElementById("readmsg_date").children[0].textContent = new Date(ts * 1000).toISOString().slice(0, 19).replace("T", " ");
107
108
	if (!isInt) {
109
		document.getElementById("readmsg_ip").hidden = false;
110
		document.getElementById("readmsg_country").hidden = false;
111
		document.getElementById("readmsg_tls").hidden = false;
112
		document.getElementById("readmsg_greet").hidden = false;
113
		document.getElementById("readmsg_timing").hidden = false;
114
		document.getElementById("readmsg_envfrom").hidden = false;
115
116
		const cc = ae.GetExtMsgCountry(num);
117
118
		document.getElementById("readmsg_ip").children[0].textContent = ae.GetExtMsgIp(num);
119
		document.getElementById("readmsg_country").textContent = getCountryFlag(cc) + " " + getCountryName(cc);
120
		document.getElementById("readmsg_tls").children[0].textContent = ae.GetExtMsgTLS(num);
121
		document.getElementById("readmsg_greet").children[0].textContent = ae.GetExtMsgGreet(num);
122
		document.getElementById("readmsg_envfrom").textContent = ae.GetExtMsgFrom(num);
123
124
		let flagText = "";
125
		if (!ae.GetExtMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
126
		if (!ae.GetExtMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
127
		if (!ae.GetExtMsgFlagPExt(num)) flagText += "<abbr title=\"The sender did not use the Extended (ESMTP) protocol\">SMTP</abbr> ";
128
		if (!ae.GetExtMsgFlagQuit(num)) flagText += "<abbr title=\"The sender did not issue the required QUIT command\">QUIT</abbr> ";
129
		if (ae.GetExtMsgFlagRare(num)) flagText += "<abbr title=\"The sender issued unusual command(s)\">RARE</abbr> ";
130
		if (ae.GetExtMsgFlagFail(num)) flagText += "<abbr title=\"The sender issued invalid command(s)\">FAIL</abbr> ";
131
		if (ae.GetExtMsgFlagPErr(num)) flagText += "<abbr title=\"The sender violated the protocol\">PROT</abbr> ";
132
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
133
	} else {
134
		document.getElementById("readmsg_ip").hidden = true;
135
		document.getElementById("readmsg_country").hidden = true;
136
		document.getElementById("readmsg_tls").hidden = true;
137
		document.getElementById("readmsg_greet").hidden = true;
138
		document.getElementById("readmsg_timing").hidden = true;
139
		document.getElementById("readmsg_envfrom").hidden = true;
140
141
		let symbol = "<span title=\"Invalid level\">&#x26a0;</span>";
142
		if (ae.GetIntMsgFrom(num) === "system") {if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"System\">&#x1f162;</span>";} // S (System)
143
		else if (ae.GetIntMsgLevel(num) === 0) symbol = "<span title=\"Level 0 User\">&#x1f10c;</span>"; // 0
144
		else if (ae.GetIntMsgLevel(num) === 1) symbol = "<span title=\"Level 1 User\">&#x278a;</span>"; // 1
145
		else if (ae.GetIntMsgLevel(num) === 2) symbol = "<span title=\"Level 2 User\">&#x278b;</span>"; // 2
146
		else if (ae.GetIntMsgLevel(num) === 3) symbol = "<span title=\"Administrator\">&#x1f150;</span>"; // A (Admin)
147
		document.getElementById("readmsg_from").innerHTML = symbol + " " + ae.GetIntMsgFrom(num);
148
149
		let flagText = "";
150
		if (!ae.GetIntMsgFlagVPad(num)) flagText += "<abbr title=\"Invalid padding\">PAD</abbr> ";
151
		if (!ae.GetIntMsgFlagVSig(num)) flagText += "<abbr title=\"Invalid signature\">SIG</abbr> ";
152
		document.getElementById("readmsg_flags").children[0].innerHTML = flagText.trim();
153
	}
154
}
155
156
// Interface
157
function addMsg(isInt, i) {
158
	const inbox = document.getElementById("tbl_inbox");
159
	const sent = document.getElementById("tbl_outbx");
160
161
	const isSent = false; //TODO
162
	const table = isSent ? sent : inbox;
163
164
	const row = table.insertRow(-1);
165
	const cellTime = row.insertCell(-1);
166
	const cellSubj = row.insertCell(-1);
167
	const cellSnd1 = row.insertCell(-1);
168
	const cellSnd2 = row.insertCell(-1);
169
170
	const ts = isInt? ae.GetIntMsgTime(i) : ae.GetExtMsgTime(i);
171
	cellTime.setAttribute("data-ts", ts);
172
	cellTime.textContent = new Date(ts * 1000).toISOString().slice(0, 10);
173
174
	cellSubj.textContent = isInt? ae.GetIntMsgTitle(i) : ae.GetExtMsgTitle(i);
175
176
	if (isInt) {
177
		cellSnd1.textContent = ae.GetIntMsgFrom(i);
178
		cellSnd1.className = (ae.GetIntMsgFrom(i).length === 16) ? "mono" : "";
179
	} else {
180
		const from1 = ae.GetExtMsgFrom(i);
181
		const from2 = from1.substring(from1.indexOf("@") + 1);
182
		const cc = ae.GetExtMsgCountry(i);
183
184
		cellSnd1.textContent = from1.substring(0, from1.indexOf("@"));
185
186
		const flag = document.createElement("abbr");
187
		flag.textContent = getCountryFlag(cc);
188
		flag.title = getCountryName(cc);
189
		cellSnd2.appendChild(flag);
190
191
		const fromText = document.createElement("span");
192
		fromText.textContent = " " + from2;
193
		cellSnd2.appendChild(fromText);
194
	}
195
196
//	divDel.innerHTML = "<input class=\"delMsg\" type=\"checkbox\" data-id=\"" + ae.GetIntMsgIdHex(i) + "\">";
197
198
	row.onclick = function() {
199
		displayMsg(isInt, i);
200
	};
201
/*
202
	cellDel.children[0].onchange = function() {
203
		if (!divDel.children[0].checked) {
204
			const checkboxes = elmt.getElementsByTagName("input");
205
			let checked = false;
206
207
			for (let j = 0; j < checkboxes.length; j++) {
208
				if (checkboxes[j].checked) {
209
					checked = true;
210
					break;
211
				}
212
			}
213
214
			if (!checked) {
215
				document.getElementById(isSent ? "btn_sentdel" : "btn_msgdel").hidden = true;
216
				return;
217
			}
218
		}
219
220
		document.getElementById(isSent? "btn_sentdel" : "btn_msgdel").hidden = false;
221
	};
222
*/
223
}
224
225
function getRowsPerPage() {
226
	const tbl = document.getElementById("tbl_inbox");
227
	tbl.innerHTML = "";
228
	const row = tbl.insertRow(-1);
229
	const cell = row.insertCell(-1);
230
	cell.textContent = "0";
231
232
	const rowsPerPage = Math.floor(getComputedStyle(document.getElementById("div_inbox")).height.replace("px", "") / getComputedStyle(document.querySelector("#tbl_inbox > tbody > tr:first-child")).height.replace("px", "")) - 1; // -1 allows space for 'load more'
233
	tbl.innerHTML = "";
234
	return rowsPerPage;
235
}
236
237
function addMessages() {
238
	const rowsPerPage = getRowsPerPage();
239
	let skipMsgs = rowsPerPage * tabs[TAB_INBOX].cur;
240
241
	const maxExt = ae.GetExtMsgCount();
242
	const maxInt = ae.GetIntMsgCount();
243
244
	tabs[TAB_INBOX].max = Math.floor((maxExt + maxInt) / rowsPerPage);
245
246
	let numExt = 0;
247
	let numInt = 0;
248
	let numAdd = 0;
249
250
	while (numAdd < rowsPerPage) {
251
		const tsInt = (numInt < maxInt) ? ae.GetIntMsgTime(numInt) : -1;
252
		const tsExt = (numExt < maxExt) ? ae.GetExtMsgTime(numExt) : -1;
253
		if (tsInt === -1 && tsExt === -1) break;
254
255
		if (tsInt !== -1 && (tsExt === -1 || tsInt > tsExt)) {
256
			if (skipMsgs > 0) skipMsgs--; else {addMsg(true, numInt); numAdd++;}
257
			numInt++;
258
		} else if (tsExt !== -1) {
259
			if (skipMsgs > 0) skipMsgs--; else {addMsg(false, numExt); numAdd++;}
260
			numExt++;
261
		}
262
	}
263
264
	if (ae.GetReadyMsgKilos() < ae.GetTotalMsgKilos()) {
265
		const inbox = document.getElementById("tbl_inbox");
266
		const row = inbox.insertRow(-1);
267
		const cell = row.insertCell(-1);
268
		cell.textContent = "Load more (" + (ae.GetTotalMsgKilos() - ae.GetReadyMsgKilos()) + " KiB left)";
269
270
		row.onclick = function() {
271
			this.onclick = "";
272
273
			ae.Message_Browse(false, function(successBrowse) {
274
				document.getElementById("tbl_inbox").style.opacity = 1;
275
276
				if (successBrowse) {
277
					addMessages();
278
					if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
279
				}
280
			});
281
		};
282
	}
283
}
284
285
function addUploaded() {
286
	const tbl = document.getElementById("tbd_uploads");
287
288
	for (let i = 0; i < ae.GetUplMsgCount(); i++) {
289
		const row = tbl.insertRow(-1);
290
		let cell;
291
		cell = row.insertCell(-1); cell.textContent = new Date(ae.GetUplMsgTime(i) * 1000).toISOString().slice(0, 10);
292
		cell = row.insertCell(-1); cell.textContent = ae.GetUplMsgTitle(i);
293
		cell = row.insertCell(-1); cell.textContent = ""; // Format
294
		cell = row.insertCell(-1); cell.textContent = ""; // Size
295
		cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\">X</button>";
296
	}
297
}
298
299
function updateAddressCounts() {
300
	document.getElementById("limit_normal").textContent = (ae.GetAddressCountNormal() + "/" + ae.GetAddressLimitNormal(ae.GetUserLevel())).padStart(ae.GetAddressLimitNormal(ae.GetUserLevel()) > 9 ? 5 : 1);
301
	document.getElementById("limit_shield").textContent = (ae.GetAddressCountShield() + "/" + ae.GetAddressLimitShield(ae.GetUserLevel())).padStart(ae.GetAddressLimitShield(ae.GetUserLevel()) > 9 ? 5 : 1);
302
	document.getElementById("limit_total").textContent = ((ae.GetAddressCountNormal() + ae.GetAddressCountShield()) + "/" + ae.GetAddrPerUser()).padStart(5);
303
}
304
305
function adjustLevel(pubkey, level, c) {
306
	const fs = document.getElementById("fs_accs");
307
	fs.disabled = true;
308
309
	ae.Account_Update(pubkey, level, function(success) {
310
		fs.disabled = false;
311
312
		if (success) {
313
			c[4].textContent = level;
314
			c[5].children[0].disabled = (level === 3);
315
			c[6].children[0].disabled = (level === 0);
316
		}
317
	});
318
}
319
320
function addAccountToTable(i) {
321
	const tblAccs = document.getElementById("tbd_accs");
322
	const row = tblAccs.insertRow(-1);
323
	let cell;
324
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserPkHex(i);
325
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSpace(i);
326
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserNAddr(i);
327
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserSAddr(i);
328
	cell = row.insertCell(-1); cell.textContent = ae.Admin_GetUserLevel(i);
329
330
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">+</button>";
331
	cell.children[0].onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(c[0].textContent, parseInt(c[4].textContent) + 1, c);};
332
	cell.children[0].disabled = (ae.Admin_GetUserLevel(i) === 3);
333
334
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">&minus;</button>";
335
	cell.children[0].onclick = function() {const c = this.parentElement.parentElement.cells; adjustLevel(c[0].textContent, parseInt(c[4].textContent) - 1, c);};
336
	cell.children[0].disabled = (ae.Admin_GetUserLevel(i) === 0);
337
338
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\">X</button>";
339
	cell.children[0].onclick = function() {
340
		const tr = this.parentElement.parentElement;
341
		ae.Account_Delete(tr.cells[0].textContent, function(success) {
342
			if (success) tr.remove();
343
		});
344
	};
345
}
346
347
function reloadAccount() {
348
	// Limits
349
	const tblLimits = document.getElementById("tbl_limits");
350
	for (let i = 0; i < 4; i++) {
351
		tblLimits.rows[i].cells[1].children[0].value = ae.GetStorageLimit(i) + 1;
352
		tblLimits.rows[i].cells[2].children[0].value = ae.GetAddressLimitNormal(i);
353
		tblLimits.rows[i].cells[3].children[0].value = ae.GetAddressLimitShield(i);
354
	}
355
356
	// Accounts
357
	const tblAccs = document.getElementById("tbd_accs");
358
359
	// All: Our account
360
	const row = tblAccs.insertRow(-1);
361
	let cell;
362
	cell = row.insertCell(-1); cell.textContent = ae.GetUserPkHex();
363
	cell = row.insertCell(-1); cell.textContent = Math.round(ae.GetTotalMsgKilos() / 1024);
364
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountNormal();
365
	cell = row.insertCell(-1); cell.textContent = ae.GetAddressCountShield();
366
	cell = row.insertCell(-1); cell.textContent = ae.GetUserLevel();
367
	cell = row.insertCell(-1); cell.innerHTML = "<button type=\"button\" autocomplete=\"off\" disabled=\"disabled\">+</button>";
368
369
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_downme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">&minus;</button>";
370
	cell.children[0].onclick = function() {
371
		const newLevel = parseInt(row.cells[4].textContent) - 1;
372
		ae.Account_Update(ae.GetUserPkHex(), newLevel, function(success) {
373
			if (success) row.cells[4].textContent = newLevel;
374
		});
375
	};
376
377
	cell = row.insertCell(-1); cell.innerHTML = "<button id=\"btn_killme\" type=\"button\" autocomplete=\"off\" disabled=\"disabled\">X</button>";
378
	cell.children[0].onclick = function() {
379
		ae.Account_Delete(ae.GetUserPkHex(), function(success) {
380
			if (success) row.remove();
381
		});
382
	};
383
384
	// Admin: Other accounts
385
	if (ae.IsUserAdmin()) {
386
		for (let i = 0; i < ae.Admin_GetUserCount(); i++) {
387
			addAccountToTable(i);
388
		}
389
	}
390
391
	document.getElementById("txt_reg").disabled = !ae.IsUserAdmin();
392
	document.getElementById("btn_reg").disabled = !ae.IsUserAdmin();
393
394
	// Contacts
395
	for (let i = 0; i < ae.GetContactCount(); i++) {
396
		addContact(
397
			ae.GetContactMail(i),
398
			ae.GetContactName(i),
399
			ae.GetContactNote(i)
400
		);
401
	}
402
403
	// Addresses
404
	for (let i = 0; i < ae.GetAddressCount(); i++) {
405
		addAddress(i);
406
	}
407
408
	updateAddressCounts();
409
}
410
411 View Code Duplication
function deleteAddress(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
412
	let btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
413
	for (let i = 0; i < btns.length; i++) btns[i].disabled = true;
414
415
	let addressToDelete = -1;
416
417
	for (let i = 0; i < ae.GetAddressCount(); i++) {
418
		if (addr === ae.GetAddress(i)) {
419
			addressToDelete = i;
420
			break;
421
		}
422
	}
423
424
	if (addressToDelete === -1) return;
425
426
	ae.Address_Delete(addressToDelete, function(success) {
427
		if (success) {
428
			document.getElementById("tbl_addrs").deleteRow(addressToDelete);
429
			document.getElementById("write_from").remove(addressToDelete);
430
			updateAddressCounts();
431
432
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) document.getElementById("btn_address_create_normal").disabled = false;
433
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) document.getElementById("btn_address_create_shield").disabled = false;
434
435
			ae.Private_Update(function(success2) {
436
				if (!success2) console.log("Failed to update the Private field");
437
438
				btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
439
				for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
440
			});
441
		} else {
442
			console.log("Failed to delete address");
443
444
			btns = document.getElementById("tbl_addrs").getElementsByTagName("button");
445
			for (let i = 0; i < btns.length; i++) btns[i].disabled = false;
446
		}
447
	});
448
}
449
450 View Code Duplication
function shieldMix(addr) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
451
	let newAddr = "";
452
453
	for (let i = 0; i < 16; i++) {
454
		switch (addr.charAt(i)) {
455
			case '1':
456
				newAddr += "1iIlL".charAt(Math.floor(Math.random() * 5));
457
				break;
458
			case '0':
459
				newAddr += "0oO".charAt(Math.floor(Math.random() * 3));
460
				break;
461
			case 'w':
462
				newAddr += "VvWw".charAt(Math.floor(Math.random() * 4));
463
				break;
464
			default:
465
				newAddr += (Math.random() > 0.5) ? addr.charAt(i) : addr.charAt(i).toUpperCase();
466
		}
467
	}
468
469
	return newAddr;
470
}
471
472
function addAddress(num) {
473
	const addrTable = document.getElementById("tbl_addrs");
474
	const row = addrTable.insertRow(-1);
475
	const cellAddr = row.insertCell(-1);
476
	const cellChk1 = row.insertCell(-1);
477
	const cellChk2 = row.insertCell(-1);
478
	const cellChk3 = row.insertCell(-1);
479
	const cellBtnD = row.insertCell(-1);
480
481
	cellAddr.textContent = ae.GetAddress(num);
482
	cellAddr.onclick = function() {
483
		if (cellAddr.textContent.length === 16)
484
			navigator.clipboard.writeText(shieldMix(cellAddr.textContent) + "@" + ae.GetDomainEml());
1 ignored issue
show
Bug introduced by
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
485
		else
486
			navigator.clipboard.writeText(cellAddr.textContent + "@" + ae.GetDomainEml());
487
	};
488
489
	cellChk1.innerHTML = ae.GetAddressAccExt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
490
	cellChk2.innerHTML = ae.GetAddressAccInt(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
491
	cellChk3.innerHTML = ae.GetAddressUse_Gk(num) ? "<input type=\"checkbox\" checked=\"checked\">" : "<input type=\"checkbox\">";
492
493
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
494
	cellBtnD.onclick = function() {deleteAddress(cellAddr.textContent);};
495
496
	const opt = document.createElement("option");
497
	opt.value = cellAddr.textContent;
498
	opt.textContent = cellAddr.textContent + "@" + ae.GetDomainEml();
499
	document.getElementById("write_from").appendChild(opt);
500
}
501
502
document.getElementById("btn_dele").onclick = function() {
503
	this.blur();
504
505
	if (tab === TAB_WRITE) {
506
		tabs[tab].cur = 0;
507
		updateTab();
508
509
		document.getElementById("write_recv").value = "";
510
		document.getElementById("write_subj").value = "";
511
		document.getElementById("write_body").value = "";
512
513
		document.getElementById("write_recv").focus();
514
	}
515
};
516
517
document.getElementById("btn_updt").onclick = function() {
518
	const btn = this;
519
	btn.disabled = true;
520
	btn.blur();
521
522
	if (tab === TAB_INBOX) {
523
		document.getElementById("tbl_inbox").style.opacity = 0.5;
524
525
		ae.Message_Browse(true, function(successBrowse) {
526
			document.getElementById("tbl_inbox").style.opacity = 1;
527
528
			if (successBrowse) {
529
				addMessages();
530
				addUploaded();
531
				btn.disabled = false;
532
			} else {
533
				console.log("Failed to refresh");
534
				btn.disabled = false;
535
			}
536
		});
537
	}
538
};
539
540
function addContact(mail, name, note) {
541
	const tbl = document.getElementById("tbl_ctact");
542
	const row = tbl.insertRow(-1);
543
	const cellMail = row.insertCell(-1);
544
	const cellName = row.insertCell(-1);
545
	const cellNote = row.insertCell(-1);
546
	const cellBtnD = row.insertCell(-1);
547
548
	cellMail.textContent = mail;
549
	cellName.textContent = name;
550
	cellNote.textContent = note;
551
	cellBtnD.innerHTML = "<button type=\"button\">X</button>";
552
553
	cellMail.contentEditable = true;
554
	cellName.contentEditable = true;
555
	cellNote.contentEditable = true;
556
557
	cellBtnD.onclick = function() {row.remove();};
558
}
559
560
document.getElementById("btn_newcontact").onclick = function() {
561
	addContact("", "", "");
562
};
563
564
document.getElementById("btn_savecontacts").onclick = function() {
565
	while (ae.GetContactCount() > 0) {
566
		ae.DeleteContact(0);
567
	}
568
569
	for (const row of document.getElementById("tbl_ctact").rows) {
570
		ae.AddContact(row.cells[0].textContent, row.cells[1].textContent, row.cells[2].textContent);
571
	}
572
573
	const btn = this;
574
	btn.disabled = true;
575
576
	ae.Private_Update(function(success) {
577
		btn.disabled = false;
578
579
		if (!success) {
580
			console.log("Failed contacts update");
581
		}
582
	});
583
};
584
585
function updateTab() {
586
	switch (tab) {
587
		case TAB_INBOX:
588
			addMessages();
589
		break;
590
591
		case TAB_WRITE:
592
			switch (tabs[tab].cur) {
593
				case 0: // Write
594
					document.getElementById("div_write_1").hidden = false;
595
					document.getElementById("div_write_2").hidden = true;
596
					document.getElementById("write_body").focus();
597
				break;
598
599
				case 1: // Verify
600
					ae.Address_Lookup(document.getElementById("write_recv").value, function(pk) {
601
						if (pk) {
602
							document.getElementById("div_write_1").hidden = true;
603
							document.getElementById("div_write_2").hidden = false;
604
605
							document.getElementById("write2_from").textContent = document.getElementById("write_from").value + "@" + ae.GetDomainEml();
606
							document.getElementById("write2_recv").textContent = document.getElementById("write_recv").value;
607
							document.getElementById("write2_pkey").textContent = sodium.to_hex(pk);
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
608
609
							document.getElementById("write2_subj").textContent = document.getElementById("write_subj").value;
610
							document.getElementById("write2_rply").textContent = document.getElementById("write_rply").textContent;
611
							document.getElementById("write2_body").textContent = document.getElementById("write_body").value;
612
						} else {
613
							console.log("Failed lookup");
614
						}
615
					});
616
				break;
617
618
				case 2: // Send
619
					ae.Message_Create(
620
						document.getElementById("write_subj").value,
621
						document.getElementById("write_body").value,
622
						document.getElementById("write_from").value,
623
						document.getElementById("write_recv").value,
624
						document.getElementById("write_rply").textContent,
625
						(document.getElementById("write2_recv").textContent.indexOf("@") > 0) ? null : sodium.from_hex(document.getElementById("write2_pkey").textContent),
1 ignored issue
show
Bug introduced by
The variable sodium seems to be never declared. If this is a global, consider adding a /** global: sodium */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
626
						function(success) {
627
							if (success) {
628
								console.log("Sent ok");
629
							} else {
630
								console.log("Failed sending");
631
							}
632
						}
633
					);
634
				break;
635
			}
636
		break;
637
638
		case TAB_NOTES:
639
			for (let i = 0; i <= tabs[tab].max; i++) {
640
				document.getElementById("div_notes").children[i].hidden = (i !== tabs[tab].cur);
641
			}
642
		break;
643
644
		case TAB_ADMIN:
645
			for (let i = 0; i <= tabs[tab].max; i++) {
646
				document.getElementById("div_admin").children[i].hidden = (i !== tabs[tab].cur);
647
			}
648
		break;
649
	}
650
651
	document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
652
	document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
653
}
654
655
document.getElementById("btn_left").onclick = function() {
656
	tabs[tab].cur--;
657
	if (tabs[tab].cur === 0) this.disabled = true;
658
	if (tabs[tab].cur < tabs[tab].max) document.getElementById("btn_rght").disabled = false;
659
	updateTab();
660
	this.blur();
661
};
662
663
document.getElementById("btn_rght").onclick = function() {
664
	tabs[tab].cur++;
665
	if (tabs[tab].cur === tabs[tab].max) this.disabled = true;
666
	document.getElementById("btn_left").disabled = false;
667
	updateTab();
668
	this.blur();
669
};
670
671
const buttons = document.querySelector("#main1 > .top").getElementsByTagName("button");
672
for (let i = 0; i < buttons.length; i++) {
673
	buttons[i].onclick = function() {
674
		tab = i;
675
676
		for (let j = 0; j < buttons.length; j++) {
677
			document.querySelector("#main1 > .mid").children[j].hidden = (tab !== j);
678
			buttons[j].disabled = (tab === j);
679
		}
680
681
		document.getElementById("btn_left").disabled = (tabs[tab].cur === 0);
0 ignored issues
show
Bug introduced by
The variable tab is changed as part of the for loop for example by i on line 674. Only the value of the last iteration will be visible in this function if it is called after the loop.
Loading history...
682
		document.getElementById("btn_rght").disabled = (tabs[tab].cur === tabs[tab].max);
683
		document.getElementById("btn_dele").disabled = !tabs[tab].btnDele;
684
		document.getElementById("btn_updt").disabled = !tabs[tab].btnUpdt;
685
	};
686
}
687
688
function addressCreate(addr) {
689
	const btnN = document.getElementById("btn_address_create_normal");
690
	const btnS = document.getElementById("btn_address_create_shield");
691
	btnN.disabled = true;
692
	btnS.disabled = true;
693
694
	ae.Address_Create(addr, function(success1) {
695
		if (success1) {
696
			ae.Private_Update(function(success2) {
697
				addAddress(ae.GetAddressCount() - 1);
698
				if (addr !== "SHIELD") document.getElementById("txt_address_create_normal").value = "";
699
				updateAddressCounts();
700
701
				if (!success2) console.log("Failed to update the Private field");
702
703
				if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
704
				if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
705
			});
706
		} else {
707
			console.log("Failed to add address");
708
709
			if (ae.GetAddressCountNormal() < ae.GetAddressLimitNormal(ae.GetUserLevel())) btnN.disabled = false;
710
			if (ae.GetAddressCountShield() < ae.GetAddressLimitShield(ae.GetUserLevel())) btnS.disabled = false;
711
		}
712
	});
713
}
714
715
document.getElementById("btn_address_create_normal").onclick = function() {
716
	if (ae.GetAddressCountNormal() >= ae.GetAddressLimitNormal(ae.GetUserLevel())) return;
717
718
	const txtNewAddr = document.getElementById("txt_address_create_normal");
719
	if (!txtNewAddr.reportValidity()) return;
720
721
	addressCreate(txtNewAddr.value);
722
};
723
724
document.getElementById("btn_address_create_shield").onclick = function() {
725
	if (ae.GetAddressCountShield() >= ae.GetAddressLimitShield(ae.GetUserLevel())) return;
726
727
	addressCreate("SHIELD");
728
};
729
730
document.getElementById("btn_reg").onclick = function() {
731
	const btn = document.getElementById("btn_reg");
732
	const txt = document.getElementById("txt_reg");
733
	if (!txt.reportValidity()) return;
734
	btn.disabled = true;
735
736
	ae.Account_Create(txt.value, function(success) {
737
		if (success) {
738
			addAccountToTable(ae.Admin_GetUserCount() - 1);
739
			txt.value = "";
740
		}
741
742
		btn.disabled = false;
743
	});
744
};
745
746
document.getElementById("chk_downme").onclick = function() {document.getElementById("btn_downme").disabled = !this.checked;};
747
document.getElementById("chk_killme").onclick = function() {document.getElementById("btn_killme").disabled = !this.checked;};
748
749
document.getElementById("btn_notepad_savesep").onclick = function() {
750
	const np = document.getElementById("txt_notepad");
751
	np.disabled = true;
752
753
	ae.Message_Upload("title", np.value, false, function(success) {
754
		if (success) {
755
			np.value = "";
756
			addUploaded();
757
		}
758
759
		console.log("Failed to add text");
760
		np.disabled = false;
761
	});
762
};
763
764
document.getElementById("txt_skey").onkeyup = function(event) {
765
	if (event.key === "Enter") {
766
		event.preventDefault();
767
		document.getElementById("btn_enter").click();
768
	}
769
};
770
771
document.getElementById("btn_enter").onclick = function() {
772
	const txtSkey = document.getElementById("txt_skey");
773
	if (!txtSkey.reportValidity()) return;
774
775
	const btn = this;
776
	btn.disabled = true;
777
	document.getElementById("txt_skey").style.background = "#233";
778
779
	ae.SetKeys(txtSkey.value, function(successSetKeys) {
780
		if (successSetKeys) {
781
			ae.Account_Browse(0, function(successBrowse) {
782
				if (successBrowse) {
783
					txtSkey.value = "";
784
785
					reloadAccount();
786
					document.getElementById("div_begin").hidden = true;
787
					document.getElementById("div_main").style.display = "grid";
788
789
					document.getElementById("btn_updt").click();
790
				} else {
791
					console.log("Failed to enter");
792
					btn.disabled = false;
793
					document.getElementById("txt_skey").style.background = "#466";
794
					txtSkey.focus();
795
				}
796
			});
797
		} else {
798
			console.log("Invalid format for key");
799
			btn.disabled = false;
800
			document.getElementById("txt_skey").style.background = "#466";
801
			txtSkey.focus();
802
		}
803
	});
804
};
805
806
});
807